package gui.batches;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import javax.swing.Timer;

import common.util.DateUtils;

import core.Container;
import core.Item;
import core.ItemFacade;
import core.Product;
import core.ProductFacade;
import gui.common.*;
import gui.inventory.*;

/**
 * Controller class for the add item batch view.
 */
public class AddItemBatchController extends ItemBatchController implements
		IAddItemBatchController {
	
	IAddItemBatchView _theView;
	
	private boolean _usingScanner;
	private boolean _countIsValid;
	private boolean _entryDateValid;
	private boolean _barcodeEmpty;
	
	private Container _container;
	
	private Timer barcodeTimer = new Timer(1000,
			new ActionListener() {
				public void actionPerformed(ActionEvent a) {
					addItem();
				}
			}
	);

	/**
	 * Constructor.
	 * 
	 * @param view Reference to the add item batch view.
	 * @param target Reference to the storage unit to which items are being added.
	 */
	public AddItemBatchController(IView view, ProductContainerData target) {
		super(view);
		_theView = (IAddItemBatchView) this._view;
		
		_usingScanner = false;
		_countIsValid = true;
		_entryDateValid = true;
		_barcodeEmpty = true;
		
		_container = target.getContainer();
		_theView.setCount("1");
		getView().setEntryDate(DateUtils.currentDate());
		_theView.setUseScanner(false);
		_theView.giveBarcodeFocus();
		construct();
	}

	/**
	 * Returns a reference to the view for this controller.
	 */
	@Override
	protected IAddItemBatchView getView() {
		return (IAddItemBatchView) super.getView();
	}

	/**
	 * Sets the enable/disable state of all components in the controller's view.
	 * A component should be enabled only if the user is currently
	 * allowed to interact with that component.
	 * 
	 * {@pre None}
	 * 
	 * {@post The enable/disable state of all components in the controller's view
	 * have been set appropriately.}
	 */
	@Override
	protected void enableComponents() {
		//add item button
		
		/*
		 * We emulate entryDateChanged here because the view can auto-correct the date
		 * if it loses focus when it is invalid.  Calling this here hints this method
		 * about that change.  We can't call entryDateChanged because that method calls
		 * this method.
		 */
		if (_theView.getEntryDate() != null)
			_entryDateValid = Item.isValidDate(DateUtils.formatDate(_theView.getEntryDate()));
		else
			_entryDateValid = false;
		
		boolean enableAddButton = true;
		if(!_countIsValid || !_entryDateValid || _usingScanner || _barcodeEmpty){
			enableAddButton = false;
		}
		_theView.enableItemAction(enableAddButton);
		//undo button
		_theView.enableUndo(canUndo());
		
		//redo button
		_theView.enableRedo(canRedo());
	}

	/**
	 * This method is called when the "Entry Date" field in the
	 * add item batch view is changed by the user.
	 */
	@Override
	public void entryDateChanged() {
		if (_theView.getEntryDate() != null)
			_entryDateValid = Item.isValidDate(DateUtils.formatDate(_theView.getEntryDate()));
		else
			_entryDateValid = false;
		enableComponents();
	}

	/**
	 * This method is called when the "Count" field in the
	 * add item batch view is changed by the user.
	 */
	@Override
	public void countChanged() {
		int count = 0;
		try{
			count = Integer.parseInt(_theView.getCount());
		}
		catch(NumberFormatException e){
			_countIsValid = false;
		}
		
		
		if(count > 0){
			_countIsValid = true;
		}
		else{
			_countIsValid = false;
		}
		enableComponents();
	}

	/**
	 * This method is called when the "Product Barcode" field in the
	 * add item batch view is changed by the user.
	 */
	@Override
	public void barcodeChanged() {
		_barcodeEmpty = _theView.getBarcode().length() == 0;
		if (_usingScanner) {

			if (_barcodeEmpty) {
				barcodeTimer.stop();
			}
			else if (barcodeTimer.isRunning()) {
				barcodeTimer.restart();
			}
			else {
				barcodeTimer.start();
			}
			
		}
		enableComponents();
	}

	/**
	 * This method is called when the "Use Barcode Scanner" setting in the
	 * add item batch view is changed by the user.
	 */
	@Override
	public void useScannerChanged() {
		_usingScanner = _theView.getUseScanner();
		enableComponents();
	}

	/**
	 * This method is called when the user clicks the "Add Item" button
	 * in the add item batch view.
	 */
	@Override
	public void addItem() {

		boolean newProduct = false;		
		if(ProductFacade.instance().getProduct(_theView.getBarcode()) == null){
			_theView.displayAddProductView();
			newProduct = true;
		}

		//get the count
		int count = -1;
		try {
			count = Integer.parseInt(_theView.getCount());
		}
		catch (NumberFormatException e) {
			//ignore it.
		}
		
		if(count <= 0){
			getView().displayErrorMessage("Count is invalid");
			resetController();
			return;
		}
		
		Product tempP = ProductFacade.instance().getProduct(_theView.getBarcode());
		if (tempP != null){
			AddItemCommand command = new AddItemCommand(tempP,_container,count,
					_theView.getEntryDate(), newProduct);
			doCommand(command);
		}
		resetController();
		

	}

	private void resetController() {
		barcodeTimer.stop();
		getView().setCount("1");
		getView().setEntryDate(DateUtils.currentDate());
		getView().setBarcode("");
		_barcodeEmpty =true;
		getView().giveBarcodeFocus();	
		enableComponents();
	}

	/**
	 * This method is called when the user clicks the "Done" button
	 * in the add item batch view.
	 */
	@Override
	public void done() {
		try {
			ItemFacade.instance().printBarcodes(_allChangedItems, "");
		} catch (IOException e) {
			getView().displayErrorMessage(e.getMessage());
		}
		getView().close();
		onDone();
	}
	
}

